package com.smart.tool.core;

import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * @Author gao.gwq
 * @Version StringTool.java, v 0.1 2024年06月20日 11:33 gao.gwq
 * @Description: TODO
 */
public class StringTool {

    public static final String EMPTY = "";

    // ---------------------- empty ----------------------
    /**
     * is empty
     *
     * <pre>
     * StringUtils.isEmpty(null)      = true
     * StringUtils.isEmpty("")        = true
     * StringUtils.isEmpty(" ")       = false
     * StringUtils.isEmpty("bob")     = false
     * StringUtils.isEmpty("  bob  ") = false
     * </pre>
     *
     * @param str
     * @return
     */
    public static boolean isEmpty(String str) {
        return str == null || str.length() == 0;
    }

    /**
     * is not empty
     *
     * <pre>
     * StringUtils.isNotEmpty(null)      = false
     * StringUtils.isNotEmpty("")        = false
     * StringUtils.isNotEmpty(" ")       = true
     * StringUtils.isNotEmpty("bob")     = true
     * StringUtils.isNotEmpty("  bob  ") = true
     * </pre>
     *
     * @param str
     * @return
     */
    public static boolean isNotEmpty(String str) {
        return !StringTool.isEmpty(str);
    }


    // ---------------------- blank ----------------------
    /**
     * is blank
     *
     * <pre>
     * StringUtils.isBlank(null)      = true
     * StringUtils.isBlank("")        = true
     * StringUtils.isBlank(" ")       = true
     * StringUtils.isBlank("bob")     = false
     * StringUtils.isBlank("  bob  ") = false
     * </pre>
     *
     * @param str
     * @return
     */
    public static boolean isBlank(String str) {
        return str == null || str.trim().length()==0;
    }

    /**
     * is not blank
     *
     * <pre>
     * StringUtils.isNotBlank(null)      = false
     * StringUtils.isNotBlank("")        = false
     * StringUtils.isNotBlank(" ")       = false
     * StringUtils.isNotBlank("bob")     = true
     * StringUtils.isNotBlank("  bob  ") = true
     * </pre>
     *
     * @param str
     * @return
     */
    public static boolean isNotBlank(String str) {
        return !StringTool.isBlank(str);
    }

    // ---------------------- trim ----------------------
    /**
     * trim
     *
     * <pre>
     * StringUtils.trim(null)          = null
     * StringUtils.trim("")            = ""
     * StringUtils.trim("     ")       = ""
     * StringUtils.trim("abc")         = "abc"
     * StringUtils.trim("    abc    ") = "abc"
     * </pre>
     *
     * @param str
     * @return
     */
    public static String trim(String str) {
        return str == null ? null : str.trim();
    }

    /**
     * trimToNull
     *
     * <pre>
     * StringUtils.trimToNull(null)          = null
     * StringUtils.trimToNull("")            = null
     * StringUtils.trimToNull("     ")       = null
     * StringUtils.trimToNull("abc")         = "abc"
     * StringUtils.trimToNull("    abc    ") = "abc"
     * </pre>
     *
     * @param str
     * @return
     */
    public static String trimToNull(String str) {
        String ts = trim(str);
        return isEmpty(ts) ? null : ts;
    }

    /**
     * trimToEmpty
     *
     * <pre>
     * StringUtils.trimToEmpty(null)          = ""
     * StringUtils.trimToEmpty("")            = ""
     * StringUtils.trimToEmpty("     ")       = ""
     * StringUtils.trimToEmpty("abc")         = "abc"
     * StringUtils.trimToEmpty("    abc    ") = "abc"
     * </pre>
     *
     * @param str
     * @return
     */
    public static String trimToEmpty(String str) {
        return str == null ? EMPTY : str.trim();
    }

    // ---------------------- isNumeric ----------------------

    /**
     * <p>Checks if the String contains only unicode digits.
     * A decimal point is not a unicode digit and returns false.</p>
     *
     * <p><code>null</code> will return <code>false</code>.
     * An empty String (length()=0) will return <code>true</code>.</p>
     *
     * <pre>
     * StringUtils.isNumeric(null)   = false
     * StringUtils.isNumeric("")     = true
     * StringUtils.isNumeric("  ")   = false
     * StringUtils.isNumeric("123")  = true
     * StringUtils.isNumeric("12 3") = false
     * StringUtils.isNumeric("ab2c") = false
     * StringUtils.isNumeric("12-3") = false
     * StringUtils.isNumeric("12.3") = false
     * </pre>
     *
     * @param str  the String to check, may be null
     * @return <code>true</code> if only contains digits, and is non-null
     */
    public static boolean isNumeric(String str) {
        if (str == null) {
            return false;
        }
        int sz = str.length();
        for (int i = 0; i < sz; i++) {
            if (Character.isDigit(str.charAt(i)) == false) {
                return false;
            }
        }
        return true;
    }

    /**
     * 格式化字符串,类似String.format，只支持%s
     * <pre>
     * example1:
     * String message = format("hello %s", "world");
     * System.out.println(message);//hello world
     * example2:
     * String message = format("hello %s", "world", "hello");
     * System.out.println(message);//hello world[hello]
     *</pre>
     * @param template
     * @param args
     * @return
     */
    public static String format(String template, Object... args) {
        template = String.valueOf(template);
        if (args == null) {
            return template;
        }
        StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
        int templateStart = 0;

        int i;
        int placeholderStart;
        for (i = 0; i < args.length; templateStart = placeholderStart + 2) {
            placeholderStart = template.indexOf("%s", templateStart);
            if (placeholderStart == -1) {
                break;
            }

            builder.append(template, templateStart, placeholderStart);
            builder.append(args[i++]);
        }

        builder.append(template, templateStart, template.length());
        if (i < args.length) {
            builder.append(" [");
            builder.append(args[i++]);

            while (i < args.length) {
                builder.append(", ");
                builder.append(args[i++]);
            }

            builder.append(']');
        }

        return builder.toString();
    }

    /**
     * 数组转字符串
     * example:
     * String join = join(",", "1","2","3","4","5","6","7","8","9","10");
     * System.out.println(join);//1,2,3,4,5,6,7,8,9,10
     * @param splitter
     * @param obj
     * @return
     */
    public static String join(String splitter, Object... obj) {

        if(StringUtils.isEmpty(splitter)){
            throw new IllegalArgumentException("splitter is null");
        }

        if (obj == null || obj.length == 0) {
            return StringUtils.EMPTY;
        }

        StringJoiner joiner = new StringJoiner(splitter);
        for (Object o : obj) {
            joiner.add(String.valueOf(o));
        }
        return joiner.toString();
    }


    /**
     * 字符串切割为队列
     * example:
     * String source = "1,2,3,4,5,6,7,8,9,10";
     * List<String> split = split(source, ",");
     * System.out.println(split);//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     *
     * @param source source
     * @param splitter splitter-character
     * @return split result
     */
    public static List<String> split(String source, String splitter) {

        if(StringUtils.isEmpty(splitter)){
            throw new IllegalArgumentException("splitter is null");
        }

        if (StringUtils.isBlank(source)) {
            return Collections.emptyList();
        }

        return Arrays.stream(source.trim().split(splitter))
                .map(String::trim)
                .collect(Collectors.toList());
    }

    /**
     * 堆栈信息转字符串
     *
     * @param trace
     * @return
     */
    public static String traceToString(StackTraceElement[] trace) {
        StringBuilder builder = new StringBuilder(512);
        builder.append("\n");
        for (StackTraceElement traceElement : trace) {
            builder.append("\t ").append(traceElement).append("\n");
        }
        return builder.toString();
    }
    /**
     * 将字符串中的字符转换为大写
     * example:
     * String reslut = upperCharacter("hello world", 0, 5);
     * System.out.println(reslut);//HELLO WORLD
     *
     * @param str
     * @param start
     * @param end
     * @return
     */
    public static String upperCharacter(String str, int start, int end) {
        if (str == null || str.trim().length() == 0) {
            throw new IllegalArgumentException("str is null");
        }
        if (start < 0) {
            throw new IllegalArgumentException("start is null");
        }
        if (end < start) {
            throw new IllegalArgumentException("end is litter than start size");
        }
        int length = str.length();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < length; i++) {
            if (i >= start && i <= end) {
                stringBuilder.append(Character.toUpperCase(str.charAt(i)));
                continue;
            }
            stringBuilder.append(str.charAt(i));
        }
        return stringBuilder.toString();
    }
}
